package com.job2e.common;

import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;

import javax.crypto.*;
import javax.crypto.spec.*;

import sun.misc.BASE64Decoder;

public class Security {
	public static String getMD5(String source) {
		return getMD5(source.getBytes());
	}
	
	public static String getMD5(byte[] source) {
	  String s = null;
	  char hexDigits[] = {       // �������ֽ�ת���� 16 ���Ʊ�ʾ���ַ�
	     '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',  'e', 'f'}; 
	   try
	   {
	    java.security.MessageDigest md = java.security.MessageDigest.getInstance( "MD5" );
	    md.update( source );
	    byte tmp[] = md.digest();          // MD5 �ļ�������һ�� 128 λ�ĳ�����
	                                                // ���ֽڱ�ʾ���� 16 ���ֽ�
	    char str[] = new char[16 * 2];   // ÿ���ֽ��� 16 ���Ʊ�ʾ�Ļ���ʹ�������ַ�
	                                                 // ���Ա�ʾ�� 16 ������Ҫ 32 ���ַ�
	    int k = 0;                                // ��ʾת������ж�Ӧ���ַ�λ��
	    for (int i = 0; i < 16; i++) {          // �ӵ�һ���ֽڿ�ʼ���� MD5 ��ÿһ���ֽ�
	                                                 // ת���� 16 �����ַ��ת��
	     byte byte0 = tmp[i];                 // ȡ�� i ���ֽ�
	     str[k++] = hexDigits[byte0 >>> 4 & 0xf];  // ȡ�ֽ��и� 4 λ������ת��, 
	                                                             // >>> Ϊ�߼����ƣ������λһ������
	     str[k++] = hexDigits[byte0 & 0xf];            // ȡ�ֽ��е� 4 λ������ת��
	    } 
	    s = new String(str);                                 // ����Ľ��ת��Ϊ�ַ�

	   }catch( Exception e )
	   {
	    e.printStackTrace();
	   }
	   return s;
	 }
	
	/*
	 * DES����
	 * @param key ��Կ
	 * @param data ����ǰ���
     * @return ���ܺ����
	 */
	public static byte[] desEncrypt(String key, byte[] data)
		throws Exception {
		//      DES�㷨Ҫ����һ�������ε������Դ
        //SecureRandom sr = new SecureRandom();
		byte rawKeyData[] = key.getBytes("UTF-8");  
        //   ��ԭʼ�ܳ���ݴ���DESKeySpec����  
        DESKeySpec dks = new DESKeySpec(rawKeyData);  
        //   ����һ���ܳ׹�����Ȼ�������DESKeySpecת����һ��SecretKey����  
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");  
        SecretKey skey = keyFactory.generateSecret(dks);   

		//���һ��˽�_������Cipher��ECB�Ǽ��ܷ�ʽ��PKCS5Padding����䷽��
		Cipher cipher=Cipher.getInstance("DES/CBC/PKCS5Padding");//"DES/CBC/PKCS5Padding"

		//��key����IV
		IvParameterSpec iv = new IvParameterSpec(rawKeyData);
		//ʹ��˽�_����
		cipher.init(Cipher.ENCRYPT_MODE, skey, iv);
		byte[] cipherText=cipher.doFinal(data);
		return cipherText;
	}
	
	/*
	 * DES����
	 */
	public static byte[] desDecrypt(String key, byte[] data)
		throws Exception {
		//      DES�㷨Ҫ����һ�������ε������Դ
        //SecureRandom sr = new SecureRandom();
		byte rawKeyData[] = key.getBytes("UTF-8");  
        //   ��ԭʼ�ܳ���ݴ���DESKeySpec����  
        DESKeySpec dks = new DESKeySpec(rawKeyData);  
        //   ����һ���ܳ׹�����Ȼ�������DESKeySpecת����һ��SecretKey����  
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");  
        SecretKey skey = keyFactory.generateSecret(dks);   

		//���һ��˽�_������Cipher��ECB�Ǽ��ܷ�ʽ��PKCS5Padding����䷽��
		Cipher cipher=Cipher.getInstance("DES/CBC/PKCS5Padding");

		//��key����IV
		IvParameterSpec iv = new IvParameterSpec(rawKeyData);
		//ʹ��˽�_����
		cipher.init(Cipher.DECRYPT_MODE, skey, iv);
		byte[] cipherText=cipher.doFinal(data);
		return cipherText;
	}
	
	/*
	 * AES加密
	 */
	public static String aesEncrypt(String pwd, String content)
		throws Exception {
		KeyGenerator kgen = KeyGenerator.getInstance("AES");
		kgen.init(128, new SecureRandom(pwd.getBytes("utf-8")));
		SecretKey secretKey = kgen.generateKey();
		byte[] enCodeFormat = secretKey.getEncoded();
		SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
		Cipher cipher = Cipher.getInstance("AES");// 创建密码器
		byte[] byteContent = content.getBytes("utf-8");
		cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
		byte[] result = cipher.doFinal(byteContent);
		return parseByte2HexStr(getBASE64(new String(result, "utf-8")).getBytes("utf-8")); // 加密
	}
	
	/*
	 * AES解密
	 */
	public static String aesDecrypt(String pwd, String content)
		throws Exception {
		byte[] data = getFromBASE64(new String(parseHexStr2Byte(content), "utf-8")).getBytes("utf-8");
		KeyGenerator kgen = KeyGenerator.getInstance("AES");
		kgen.init(128, new SecureRandom(pwd.getBytes("utf-8")));
		SecretKey secretKey = kgen.generateKey();
		byte[] enCodeFormat = secretKey.getEncoded();
		SecretKeySpec key = new SecretKeySpec(enCodeFormat, "AES");
		Cipher cipher = Cipher.getInstance("AES");// 创建密码器
		cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
		byte[] result = cipher.doFinal(data);
		return new String(result); // 加密
	}
	
	public static String parseByte2HexStr(byte buf[]) {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < buf.length; i++) {
			String hex = Integer.toHexString(buf[i] & 0xFF);
			if (hex.length() == 1) {
				hex = '0' + hex;
			}
			sb.append(hex.toUpperCase());
		}
		return sb.toString();
	}

	public static byte[] parseHexStr2Byte(String hexStr) {
		if (hexStr.length() < 1)
			return null;
		byte[] result = new byte[hexStr.length() / 2];
		for (int i = 0; i < hexStr.length() / 2; i++) {
			int high = Integer.parseInt(hexStr.substring(i * 2, i * 2 + 1), 16);
			int low = Integer.parseInt(hexStr.substring(i * 2 + 1, i * 2 + 2),
					16);
			result[i] = (byte) (high * 16 + low);
		}
		return result;
	}
	
	/**
     * 16������ʾ���
     *
     * @param value �ֽ�����
     * @return
     */
    public static String toHexString(byte[] value) {
        String newString = "";
        for (int i = 0; i < value.length; i++) {
            byte b = value[i];
            String str = Integer.toHexString(b);
            if (str.length() > 2) {
                str = str.substring(str.length() - 2);
            }
            if (str.length() < 2) {
                str = "0" + str;
            }
            newString += str;
        }
        return newString.toUpperCase();
    }
    
    /**
     * 16������ʾ���
     *
     * @param value �ֽ�����
     * @return
     */
    public static byte[] fromHexString(String value) {
    	final int hexNum = 2;
    	final int hexRadix = 16;
    	
        int count = value.length() / hexNum;
        int beginIndex = 0;
        int endIndex = hexNum;
        byte[] buf = new byte[count];
        for (int i=0; i<count; i++) {
        	beginIndex = i * hexNum;
        	endIndex = (i + 1) * hexNum;
        	
        	String str = value.substring(beginIndex, endIndex);
        	buf[i] = (byte)Integer.parseInt(str, hexRadix);
        }
        return buf;
    }
    
    public static String[] shortUrl(String url)  
    {  
        //可以自定义生成MD5加密字符传前的混合KEY  
        String key = "haohao-com";  
       
        //对传入网址进行MD5加密  
        String hex = getMD5(key + url);
       
        String[] resUrl = new String[4];
      
        for (int i = 0; i < 4; i++) {  
            //把加密字符按照8位一组16进制与0x3FFFFFFF进行位与运算  
            long hexint = 0x3FFFFFFF & Long.valueOf(hex.substring(i * 8, i * 8 + 8).toUpperCase(), 16);  
            String outChars = ""; 
            for (int j = 0; j < 6; j++) {  
                //把得到的值与0x0000003D进行位与运算，取得字符数组chars索引  
                long index = 0x0000003D & hexint;
                //把取得的字符相加 
                outChars += codeArray[(int)index];
                //每次循环按位右移5位 
                hexint = hexint >> 5;
            }
            //把字符串存入对应索引的输出数组  
            resUrl[i] = outChars;
        }
        return resUrl;
    } 
    
	public static String getBASE64(String s) {
		if (s == null)
			return null;
		return (new sun.misc.BASE64Encoder()).encode(s.getBytes());
	}

	// 将 BASE64 编码的字符串 s 进行解码
	public static String getFromBASE64(String s) {
		if (s == null)
			return null;
		BASE64Decoder decoder = new BASE64Decoder();
		try {
			byte[] b = decoder.decodeBuffer(s);
			return new String(b);
		} catch (Exception e) {
			return null;
		}
	}
	
	private static String[] codeArray = new String[]{
            "a","b","c","d","e","f","g","h",  
            "i","j","k","l","m","n","o","p",  
            "q","r","s","t","u","v","w","x",  
            "y","z","0","1","2","3","4","5",  
            "6","7","8","9","A","B","C","D",  
            "E","F","G","H","I","J","K","L",  
            "M","N","O","P","Q","R","S","T",  
            "U","V","W","X","Y","Z"  
        };
	
	public static String getCodeFromNumber(int num) {
		int i = num;
		if (i < 0) {
			i = 0 - i;
		}
		return codeArray[num % codeArray.length];
	}

	public static String getCodeString(String str) {
		byte[] bs = str.getBytes();
		String ret = "";
		for (byte b : bs) {
			ret += getCodeFromNumber(b);
		}
		return ret;
	}
}
